package com.roy.roycodegenerator.common.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

public class FtpUtil {

    /**
     * 日志处理类
     */
    private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);

    @Autowired
    private static JdbcTemplate jdbcTemplate;

    /**
     * 功能描述: 获取FTP服务器 <br>
     * 
     * @return
     * @see
     * @since 1.5
     */
    private FTPClient ftpChannel(String host, String user, String pwd, String port) {
        FTPClient ftp = null;
        if (notBlank(host, port, user, pwd)) {
            try {
                ftp = new FTPClient();
                ftp.connect(host, Integer.parseInt(port));
                ftp.login(user, pwd);
                if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                    ftp.disconnect();
                    ftp = null;
                    logger.error("FTP server refused connection");
                    return ftp;
                }
            } catch (Exception e) {
                logger.error("login FTP server failed", e);
            }
        }
        return ftp;
    }

    /**
     * 功能描述: 验证配置信息 <br>
     * 
     * @param host 主机地址
     * @param port 端口
     * @param user 用户名
     * @param pwd 密码
     * @return
     * @see
     * @since 1.5
     */
    private boolean notBlank(String host, String port, String user, String pwd) {
        boolean suc = false;
        String format = "ftpserver.properties file {} property no config!";
        if (host == null || "".equals(host)) {
            logger.debug(format, "host");
            return suc;
        }
        if (port == null || "".equals(port)) {
            logger.debug(format, "port");
            return suc;
        }
        if (user == null || "".equals(user)) {
            logger.debug(format, "user");
            return suc;
        }
        if (pwd == null || "".equals(pwd)) {
            logger.debug(format, "pwd");
            return suc;
        }
        suc = true;
        return suc;
    }

    /**
     * 功能描述: 创建不存在的目录文件 <br>
     * 
     * @param ftp
     * @param path
     * @see
     * @since 1.5
     */
    private void createDirs(FTPClient ftp, String path) {
        boolean result = false;
        String[] sub = path.split("/");
        int length = sub.length;
        int i = 1;
        String paths = "/";
        try {
            if (ftp.changeWorkingDirectory(path)) {
                result = true;
            }
            while (!result) {
                if (i > length - 1) {
                    break;
                }
                paths += sub[i] + "/";
                if (!ftp.changeWorkingDirectory(paths)) {
                    ftp.makeDirectory(paths);
                }
                ++i;
            }
        } catch (IOException e) {
            logger.error("FTP创建文件夹失败" + e.getMessage());
        }
    }

    /**
     * 功能描述: 上传贷款信息报表至FTP服务器 <br>
     * 
     * @param fileName 文件名
     * @param input 文件输入流
     * @return
     * @see
     * @since 1.5
     */
    public String uploadCirFile(String fileName, InputStream input, FtpInfo ftpInfo) {

        FTPClient ftp = ftpChannel(ftpInfo.getHostname(), ftpInfo.getUsername(), ftpInfo.getPassword(),
                String.valueOf(ftpInfo.getPort()));
        String workdir = ftpInfo.getPath() + fileName.substring(0, fileName.indexOf("."));
        createDirs(ftp, workdir);

        try {
            // 生成文件
            ftp.changeWorkingDirectory(workdir);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.storeFile(fileName, input);
            input.close();
            ftp.logout();

            return workdir + "/" + fileName;
        } catch (Exception e) {
            logger.error("信息报送文件上传贷款信息报表至FTP服务器失败", e);
            return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.error("uploadToFbiFile" + ioe);
                }
            }
        }
    }

    /**
     * 功能描述: 上传贷款信息报表至FTP服务器 <br>
     * 
     * @param fileName 文件名
     * @param input 文件输入流
     * @return
     * @see
     * @since 1.5
     */
    public void uploadLogFile(String fileName, InputStream input, FtpInfo ftpInfo) {

        FTPClient ftp = ftpChannel(ftpInfo.getHostname(), ftpInfo.getUsername(), ftpInfo.getPassword(),
                String.valueOf(ftpInfo.getPort()));
        String workdir = ftpInfo.getPath();
        createDirs(ftp, workdir);

        try {
            // 生成文件
            ftp.changeWorkingDirectory(workdir);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.storeFile(fileName, input);
            input.close();
            ftp.logout();
            logger.debug("上传日志log到ftp成功");
            // return workdir + "/" + fileName;
        } catch (Exception e) {
            logger.error("信息报送文件上传贷款信息报表至FTP服务器失败", e);
            // return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.error("uploadToFbiFile" + ioe);
                }
            }
        }
    }

    /**
     * 功能描述: 上传贷款报表至FBI FTP服务器 <br>
     * add by hu kaiyue
     * 
     * @param fileName 文件名
     * @param input 文件输入流
     * @return
     * @see
     * @since 1.5
     */
    public String uploadToFbiFile(String fileName, InputStream input, FtpInfo ftpInfo, String fileDate) {

        FTPClient ftp = ftpChannel(ftpInfo.getHostname(), ftpInfo.getUsername(), ftpInfo.getPassword(),
                String.valueOf(ftpInfo.getPort()));
        String workdir = ftpInfo.getPath() + fileDate;
        createDirs(ftp, workdir);

        try {
            // 生成文件
            ftp.changeWorkingDirectory(workdir);
            ftp.storeFile(fileName, input);
            input.close();
            ftp.logout();

            return workdir + "/" + fileName;
        } catch (Exception e) {
            logger.error("上传贷款报表至FBI FTP服务器失败", e);
            return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.error("uploadToFbiFile" + ioe);
                }
            }
        }
    }

    /**
     * 功能描述: 上传贷款信息报表至FTP服务器 <br>
     * 
     * @param fileName 文件名
     * @param input 文件输入流
     * @return
     * @see
     * @since 1.5
     */
    public boolean downloadFile(String fileName, OutputStream out, FtpInfo ftpInfo, int fileType) {

        FTPClient ftp = ftpChannel(ftpInfo.getHostname(), ftpInfo.getUsername(), ftpInfo.getPassword(),
                String.valueOf(ftpInfo.getPort()));

        boolean r = false;

        try {
            if (ftp != null) {
                ftp.setFileType(fileType);
                r = ftp.retrieveFile(fileName, out);
            }
        } catch (Exception e) {
            logger.error("从FTP服务器下载文件失败。", e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.error("downloadFile" + ioe);
                }
            }
        }

        return r;
    }

    public static File downLoadFiles(String remoteFileName, String fileRealNames, String remoteFilePath,
            String remotePath, FtpInfo ftpInfo, String tempPath, int fileType) { // 文件名称
        // String tempRemoteFilePath = remoteFileName.substring(0, remoteFileName.lastIndexOf("."));
        // File file = new File(tempPath + File.separator + tempRemoteFilePath);
        // if (!file.exists()) {
        // file.mkdirs();
        // }

        // response.setHeader("Content-disposition", "attachment;filename=" + fileRealNames);
        File file = new File(tempPath + File.separator + fileRealNames);
        OutputStream out = null;

        try {
            // fileRealNames = new String(fileRealNames.getBytes(), "ISO8859-1");
            out = new FileOutputStream(file);
            // 从ftp下载
            // response.setCharacterEncoding("UTF-8");

            String path = remotePath + remoteFilePath;

            remoteFileName = path + "/" + remoteFileName;

            FtpUtil ftpUtil = new FtpUtil();
            ftpInfo.setPath(remotePath);

            ftpUtil.downloadFile(remoteFileName, out, ftpInfo, fileType);

            out.flush();
            out.close();

        } catch (IOException e1) {
            logger.error("downLoadFiles" + e1);
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                    out = null;
                }

            } catch (IOException ex) {
                logger.error("fileToZip" + ex);
            }
        }
        return file;

    }

    /**
     * 将存放在sourceFilePath目录下的源文件，打包成fileName名称的zip文件，并存放到zipFilePath路径下
     * 
     * @param sourceFilePath :待压缩的文件路径
     * @param zipFilePath :压缩后存放路径
     * @param fileName :压缩后文件的名称
     * @return
     */
    public static void fileToZip(List<File> files, String sourceFilePath, String zipFilePath, String fileName) {
        File sourceFile = new File(sourceFilePath);
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bfos = null;
        ZipOutputStream zos = null;

        if (sourceFile.exists() == false) {
            logger.debug("待压缩的文件目录：" + sourceFilePath + "不存在.");
        } else {
            try {
                File zipFile = new File(zipFilePath + File.separator + fileName + ".zip");
                if (zipFile.exists()) {
                    logger.debug(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
                    zipFile.delete();
                    zipFile = new File(zipFilePath + File.separator + fileName + ".zip");
                }

                fos = new FileOutputStream(zipFile);
                bfos = new BufferedOutputStream(fos);
                zos = new ZipOutputStream(bfos);
                int index = 0;
                Set<String> existFile = new HashSet<String>();
                byte[] bufs = new byte[1024 * 10];
                for (int i = 0; i < files.size(); i++) {

                    File file = files.get(i);
                    String name = file.getName();

                    if (existFile.contains(name)) {
                        String type = name.substring(name.lastIndexOf(".") + 1);
                        String fileRealName = name.substring(0, name.lastIndexOf("."));
                        name = fileRealName + "_" + index + "." + type;
                        index++;
                    }
                    existFile.add(name);
                    // 创建ZIP实体，并添加进压缩包
                    ZipEntry zipEntry = new ZipEntry(name);
                    zos.putNextEntry(zipEntry);
                    // 读取待压缩的文件并写进压缩包里
                    fis = new FileInputStream(files.get(i));
                    bis = new BufferedInputStream(fis, 1024 * 10);
                    int read = 0;
                    while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
                        zos.write(bufs, 0, read);
                    }

                    try {
                        if (null != bis) {
                            bis.close();
                            bis = null;
                        }
                    } catch (IOException e) {
                        logger.error("fileToZip" + e);
                    }

                    try {
                        if (null != fis) {
                            fis.close();
                            fis = null;
                        }
                    } catch (IOException e) {
                        logger.error("fileToZip" + e);
                    }

                }
            } catch (FileNotFoundException e) {
                logger.error("fileToZip" + e);
            } catch (IOException e) {
                logger.error("fileToZip" + e);
            } finally {
                // 关闭流

                try {
                    if (null != zos) {
                        zos.flush();
                        zos.close();
                        zos = null;
                    }
                } catch (IOException e) {
                    logger.error("fileToZip" + e);
                }

                try {
                    if (null != bfos) {
                        bfos.flush();
                        bfos.close();
                        bfos = null;
                    }
                } catch (IOException e) {
                    logger.error("fileToZip" + e);
                }

                try {
                    if (null != fos) {
                        fos.flush();
                        fos.close();
                        fos = null;
                    }

                } catch (IOException e) {
                    logger.error("fileToZip" + e);
                }
            }
        }
    }

}
